import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { SuperRequestConfig, SuperRequestInterceptors } from './types'
import 'element-plus/es/components/loading/style/css'
import { ElLoading, ElMessage } from 'element-plus'

const DEFAULT_LOADING = true

const showError = (msg: string) => {
  ElMessage.error(msg)
}
class SuperRequest {
  instance: AxiosInstance
  interceptors?: SuperRequestInterceptors
  showLoading?: boolean
  needToken?: boolean
  loading?: any

  constructor(config: SuperRequestConfig) {
    this.instance = axios.create(config)
    /** 为单个实例添加拦截器 */
    this.interceptors = config.interceptors
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )
    this.showLoading =
      config.showLoading === undefined ? DEFAULT_LOADING : config.showLoading
    this.needToken = config.needToken === undefined ? true : !!config.needToken
    /** 为全局实例添加拦截器 */
    this.instance.interceptors.request.use(
      (config) => {
        //添加header
        config.headers['Channel'] = 'pc'
        // 如果有访问令牌，则添加到请求头中
        const token = localStorage.getItem('accessToken')
        if (this.needToken && token) {
          config.headers['Authorization'] = `Bearer ${token}`
          // config.headers.token = token // 将 Token 添加到 Authorization 中
        }
        if (this.showLoading) {
          //以服务的方式调用。因为loading是单例，调用多次不会重复创建
          this.loading = ElLoading.service({
            lock: true,
            text: '正在执行',
            background: 'rgb(0,0,0,0.2)',
            fullscreen: true,
          })
        }
        return config
      },
      (err) => {
        throw err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        this.loading?.close()
        if (res.config.responseType == 'blob') {
          const blob = new Blob([res.data], {
            type: res.headers['content-type'],
          })
          return { code: 200, msg: '成功', data: blob }
        }
        if (res.data.code == 401) {
          setTimeout(() => {
            setTimeout(() => {
              localStorage.clear()
              location.href = '/login'
            }, 700)
          }, 100)
        }
        return res.data
      },
      (err) => {
        this.loading?.close()
        showError(err.message)
        throw err
      }
    )
  }
  request<T = any>(config: SuperRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      if (config.showLoading === false) {
        this.showLoading = config.showLoading
      }
      this.instance
        .request<T, T>(config)
        .then((res) => {
          resolve(res)
        })
        .catch((err) => {
          reject(err)
          return err
        })
        .finally(() => {
          this.showLoading = DEFAULT_LOADING
        })
    })
  }
  get<T = any>(config: SuperRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'GET' })
  }
  post<T = any>(config: SuperRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'POST' })
  }
  delete<T = any>(config: SuperRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'DELETE' })
  }
  patch<T = any>(config: SuperRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'PATCH' })
  }
}
export default SuperRequest
